package com.keqiang.chart.impl.radar.impl

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.text.TextPaint
import com.keqiang.chart.animation.Animator
import com.keqiang.chart.impl.radar.render.IDataRender
import com.keqiang.chart.utils.ObjectPool
import com.keqiang.chart.utils.toRadian
import kotlin.math.cos
import kotlin.math.sin

/**
 * 雷达图数据绘制器
 *
 * @author Created by wanggaowan on 2022/10/28 10:04
 */
open class RadarChartDataRender(val chart: RadarChart) : IDataRender() {

    override fun onDraw(canvas: Canvas, startAngle: Float) {
        val animator = chart.animator
        val radius = chart.radius - chart.xAxis.lineEndPadding
        if (radius <= 0) {
            return
        }

        val xAxis = chart.xAxis
        val yAxis = chart.yAxis
        val stepAngle = 360f / xAxis.labelCount
        val path = ObjectPool.obtainPath()
        val (cx, cy) = chart.getCenter()
        val range = yAxis.max - yAxis.min
        val animProgress = animator.getProgress()

        val paint = ObjectPool.obtainPaint<Paint>()
        paint.style = Paint.Style.STROKE

        chart.data?.forEach {
            if (it.values.isNotEmpty()) {
                path.reset()
                for (index in it.values.indices) {
                    val data = it.values[index]
                    if (data.xIndex < 0 || data.xIndex >= xAxis.labelCount) {
                        continue
                    }

                    val percent = if (range <= 0) 0f else (data.value - yAxis.min) / range
                    val radian = (startAngle + stepAngle * data.xIndex).toRadian
                    val x = cx + cos(radian) * radius * percent * animProgress
                    val y: Float = cy + sin(radian) * radius * percent * animProgress
                    data.drawRectF.set(x, y, x, y)
                    if (index == 0) {
                        path.moveTo(x, y)
                    } else {
                        path.lineTo(x, y)
                    }
                }
                path.close()
                if (!path.isEmpty) {
                    if (it.fillBg) {
                        drawFillBg(canvas, path, it, cx, cy, radius)
                    }
                    paint.color = it.lineColor
                    paint.strokeWidth = it.lineWidth
                    canvas.drawPath(path, paint)
                    drawValueTextAndIndicator(canvas, it, animator)
                }
            }
        }

        ObjectPool.recyclePath(path)
        ObjectPool.recyclePaint(paint)

        if (chart.animator.getProgress() == 1f) {
            chart.touchHandler?.touchData?.let {
                it.forEach { entity ->
                    chart.highLightRender?.onDraw(canvas, entity)
                }
            }
        }
    }

    /**
     * 绘制折线背景填充色
     */
    protected open fun drawFillBg(canvas: Canvas, path: Path, radarData: RadarData, cx: Float, cy: Float, radius: Float) {
        if (radarData.fillBgDrawable != null) {
            radarData.fillBgDrawable?.let {
                it.setBounds((cx - radius).toInt(), (cy - radius).toInt(), (cx + radius).toInt(), (cy + radius).toInt())

                canvas.save()
                canvas.clipPath(path)
                it.draw(canvas)
                canvas.restore()
            }
        } else if (radarData.fillBgColor != 0) {
            canvas.save()
            canvas.clipPath(path)
            canvas.drawColor(radarData.fillBgColor)
            canvas.restore()
        }
    }

    /**
     * 绘制文本值和数值指示器
     */
    protected open fun drawValueTextAndIndicator(canvas: Canvas, radarData: RadarData, animator: Animator?) {
        val textPaint = ObjectPool.obtainPaint<TextPaint>(true)

        for (index in radarData.values.indices) {
            val entity = radarData.values[index]
            if (entity.isDraw) {
                var indicatorOffset = entity.labelOffset
                if (entity.drawIndicator && entity.indicatorDrawable != null
                    && entity.indicatorSize > 0) {
                    val half = entity.indicatorSize / 2f
                    entity.indicatorDrawable?.setBounds((entity.drawRectF.left - half).toInt(), (entity.drawRectF.top - half).toInt(),
                        (entity.drawRectF.left + half).toInt(), (entity.drawRectF.top + half).toInt())
                    entity.indicatorDrawable?.draw(canvas)
                    indicatorOffset += half
                }

                val progress = animator?.getProgress() ?: 1f
                val label = entity.label
                if (entity.drawLabel && !label.isNullOrEmpty() && entity.labelTextSize > 0 && progress >= 1f) {
                    textPaint.textSize = entity.labelTextSize
                    textPaint.color = entity.labelColor
                    textPaint.textAlign = Paint.Align.CENTER
                    val y = entity.drawRectF.top - indicatorOffset
                    canvas.drawText(label, entity.drawRectF.left, y, textPaint)
                }
            }
        }

        ObjectPool.recyclePaint(textPaint)
    }
}